package cn.itcast.netty.c3;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import javax.swing.*;
import java.nio.charset.Charset;

@Slf4j
public class EventLoopServer {
    public static void main(String[] args) {
        // 假如读写操作很大 那么这个selector下的 负责读写的线程就会很慢,那么对这个selector下管理的客户端线程都会很不友好
        // 我们就可以在继续细分 在原先的基础上再套一个eventLoopGroup 让这个eventLoopGroup单独去处理io操作
        EventLoopGroup group = new DefaultEventLoopGroup();
        new ServerBootstrap()
                // 可以职责跟清晰一些，区分开boss(只负责accept事件) 跟 worker(只负责读写)
                // 则是用两个参数的group()即可 然后他们的线程数就也可以自己设定了
                .group(new NioEventLoopGroup(), new NioEventLoopGroup(2))
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        //这里面有两个channelRead虽然是用不同的group来处理，每次一个线程来这两个channelRead()方法就会依次执行
                        //这里就表示用本身的ServerBootstrap下的group来处理
                        ch.pipeline().addLast("handler1",new ChannelInboundHandlerAdapter() { //名字 跟处理的实现
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                ByteBuf buf = (ByteBuf) msg;
                                //字符集一般要自己指定，因为服务器跟客户端的字符集可能不同
                                //这里是因为都是用同个电脑当服务器跟客户端所以可以偷懒直接写默认就行
                                //把数据转换为字符串 因为这里没配置转换的处理器 所以我们自己处理一下
                                log.debug(buf.toString(Charset.defaultCharset()));
                                //将消息传递给下一个handler 所以handler1处理完就可以给到handler2了 它是根据顺序依次执行handler的
                                //自定义handler时这句代码是得写的别忘了 不写的话消息到这里就断了不会往下传递了
                                ctx.fireChannelRead(msg);
                            }
                        });
                        //在这里就表示用外面的自己定义的group来处理
                        ch.pipeline().addLast(group,"handler2",new ChannelInboundHandlerAdapter() { //谁来处理 名字 跟处理的实现
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                ByteBuf buf = (ByteBuf) msg;
                                //字符集一般要自己指定，因为服务器跟客户端的字符集可能不同
                                //这里是因为都是用同个电脑当服务器跟客户端所以可以偷懒直接写默认就行
                                //把数据转换为字符串 因为这里没配置转换的处理器 所以我们自己处理一下
                                log.debug(buf.toString(Charset.defaultCharset()));
                            }
                        });

                    }
                })
                .bind(8080);


    }
}
